home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
asm
/
clockjc.exe
/
CLOCK.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-10-21
|
9KB
|
327 lines
; To create the EXE file copy makefile and clock.asm into
; the same directory and run MAKE.
; Compiled with TASM 3.1
; Linked with TLINK 3.1
; Clock - Assembly language clock in .EXE format
; This program creates screen clock in the upper right hand corner
; of the screen. Format HH:MM:SS. This program creates the clock then
; waits for keyboard input and removes the clock.
; The clock itself is installed as an ISR using
; INT 1C, USER TIMER TICK, which tick 18 times per second.
; See the comments in the code for exact implementation details
;
; This code is given to the public domain and is free. The only
; condition is that it be distributed without modifications of
; any kind.
; Author: Joe L. Chavez
; CIS [75470, 3627]
; Creation Date: 10/21/92
DOSSEG ;indicate DOS segment conventions
.8086 ;select the processor
.MODEL SMALL ;select the model
.STACK 2000h ;reserve stack space as needed for application
.DATA
; clock data area
ESSEG DW ?
CLKFLG DB 1 ;clock on/off flag
SEC DB 0 ;second (binary)
MIN DB 0 ;minute
HOU DB 0 ;hour
TICCNT DB 18 ;tick counter
SECCNT DB 0 ;second counter (for calibration)
CPOS DW 0 ;cursor position
CMODE DB 0 ;current video state
MODES DB 0,1,2,3,1,0,2,2 ;decoded modes
TIMSTR DB ' ' ;space before time
HOUR DW 0 ;hour (ascii)
DB ':'
MINUTE DW 0 ;minute
DB ':'
SECOND DW 0 ;second
; Constants
CYAN EQU 011B
COLOR EQU CYAN ;clock color
ROW EQU 0 ;put clock on top row
SCRINT EQU 10H ;screen control interrupt
SCP EQU 2 ;set cursor position
GCP EQU 3 ;get curosr position
WCHAR EQU 9 ;write character
GVS EQU 15 ;get video state
.CODE
;This marks the start of executable code
.startup
;EXE program has all available memory allocated to it
; get time on new second
MOV AH,2CH
INT 21H ;get time
MOV SEC,DH ;save second
NEWSEC: MOV AH,2CH
INT 21H ;get time again
CMP SEC,DH ;same second?
JZ NEWSEC ;wait for a new second
MOV SEC,DH ;set seconds
MOV WORD PTR MIN,CX ;set minutes, hours
; preserve the registers
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
PUSH BP
; save ES so it can be used in Clock
MOV ESSEG, ES
; disable ints while installing new ISR
CLI
; save old int
MOV AX, 351Ch
INT 21h
; here we store the Old INT 1C in a
; memory location that resides in the
; code segment so that it can be called
; in Clock without knowing the correct DS
MOV WORD PTR CS:OLDINT1C, BX
MOV WORD PTR CS:OLDINT1C+2, ES
; set new int 1C
MOV AX, 251Ch
MOV DX, SEG Clock
MOV DS, DX
MOV DX, OFFSET Clock
INT 21h
; enable interrupts
STI
L1:
; now get a char
MOV AH, 1
INT 16h
JNZ QUIT
JMP L1
; to restore the old int vector
QUIT:
; disable interrupts while installing Old INT 1C
CLI
MOV AX, 251Ch
MOV DX, WORD PTR CS:OLDINT1C
MOV BX, WORD PTR CS:OLDINT1C+2
MOV DS, BX
INT 21h
STI
; restore the regs
POP BP
POP ES
POP DS
POP SI
POP DI
POP DX
POP CX
POP BX
POP AX
;Exit to DOS when complete
MOV AX,4C01H
INT 21H
RET
; this is the pointer to the FAR address
; of the Old INT 1C procedure
OLDINT1C DD ?
;Arguments to this procedure:
;ES=PSP address (for command-line arguments)
;Must return an exit value in AL
Clock PROC NEAR
; preserve the regs used in this proc
PUSH DS
PUSH ES
PUSH AX
; get the DATA & EXTRA segment for this program
MOV AX, @DATA
MOV DS, AX
MOV AX, ESSEG
MOV ES, AX
; start clock processing
DEC TICCNT ;decrement tick counter
JNZ RT1 ;not timed out
MOV TICCNT,18 ;else, reset tick counter
MOV AL,SEC ;get seconds
INC AL ;add one
CMP AL,60 ;60 seconds?
MOV SEC,AL ;reset seconds
JNZ CHKFLG ;not a minute, check flag
MOV SEC,0 ;else, zero seconds
MOV AL,MIN ;get minutes
INC AL ;add one
CMP AL,60 ;60 minutes?
MOV MIN,AL ;reset minutes
JNZ CHKFLG ;not an hour
MOV MIN,0 ;else, zero minutes
MOV AL,HOU ;get hour
INC AL ;add one
CMP AL,24 ;24 hours?
MOV HOU,AL ;reset hours
JNZ CHKFLG ;not a day
MOV HOU,0 ;else, zero hour
CHKFLG: CMP CLKFLG,0 ;clock enabled?
JZ RT1 ;if so, update screen clock
CALL UPDATE
RT1:
; restore the regs
POP AX
POP ES
POP DS
; setup for the call to the Old INT 1C
PUSHF
CALL CS:OLDINT1C
IRET
Clock ENDP
; Update the screen
UPDATE PROC NEAR
; preserver regs used by this procedure
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH BP
MOV CLKFLG,0
MOV AL,HOU ;get hours
CALL CONASC ;convert to ascii
MOV HOUR,AX ;result to buffer
MOV AL,MIN ;get minutes
CALL CONASC ;convert to ascii
MOV MINUTE,AX ;result to buffer
MOV AL,SEC ;get seconds
CALL CONASC ;convert to ascii
MOV SECOND,AX ;result to buffer
MOV AH,GVS
INT SCRINT ;get video state
PUSH BX ;save page
MOV BX,OFFSET MODES ;point to video modes
XLAT ;get mode code
MOV CMODE,AL ;save decoded mode
POP BX ;get page
MOV AH,GCP
INT SCRINT ;get cursor position
MOV CPOS,DX ;save it
MOV DH,ROW ;get row for clock
MOV DL,31 ;assume column 31
CMP BYTE PTR CMODE,2 ;80 column mode?
JB PTIME0 ;no
MOV DL,71 ;else, set column 71
PTIME0: MOV AH,SCP
INT SCRINT ;set cursor position to time area
MOV CX,9 ;set a counter
MOV BL,WHITE ;assume white color
CMP BYTE PTR CMODE,0 ;40 column B/W?
JZ PTIME1 ;yes
CMP BYTE PTR CMODE,2 ;80 column B/W?
JZ PTIME1
MOV BL,COLOR ;else, use color
PTIME1: MOV SI,OFFSET TIMSTR ;point to time string
PTMLP: LODSB ;get a digit
PUSH CX ;save counter
PUSH SI ;save pointer
CALL PDIGIT ;print digit
POP SI
POP CX
LOOP PTMLP ;loop until done
PDONE: MOV AH,SCP
MOV DX,CPOS
INT SCRINT ;restore cursor to user's position
MOV CLKFLG,1
; restore the regs
POP BP
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
RET
UPDATE ENDP
CONASC PROC NEAR